package com.lin.fengxiu.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lin.fengxiu.exception.http.ParameterException;
import com.lin.fengxiu.model.User;
import com.lin.fengxiu.repository.UserRepository;
import com.lin.fengxiu.util.JwtToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @ClassName WxAuthenticationService
 * @Description 微信登陸
 * @Author wushaopei
 * @Date 2021/3/18 23:03
 * @Version 1.0
 */
@Service
public class WxAuthenticationService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ObjectMapper mapper;

    @Value("${wx.code2session}")
    private String code2SessionUrl;

    @Value("${wx.appid}")
    private String appid;

    @Value("${wx.appsecret}")
    private String appsecret;

    /**
     * @Description TODO ① 訪問微信服務器，驗證 code 是否合法，有沒有过期  ② 如果合法，就生成一個 JWT 令牌並返回
     *                TODO  访问条件：需要向微信传递的参数有：code码、小程序appid、
     * @param code
     * @return
     */
    public String code2Session(String code){
        // 1.组装请求参数
        String url = MessageFormat.format(this.code2SessionUrl,this.appid,this.appsecret,code);
        // 2.使用RestTemplate发送请求
        RestTemplate rest = new RestTemplate();
        Map<String, Object> session = new HashMap<>();
        // 3.发送请求并获取返回的参数，为 String类型，需进行反序列化
        String sessionText = rest.getForObject(url,String.class);
        try{
            // 4.反序列化微信服务器返回的验证结果： sessionid 、openid
            session = mapper.readValue(sessionText, Map.class);
        }catch (JsonProcessingException e){
            e.printStackTrace();
        }
        return this.registerUser(session);
    }

    /**
     * @Description 使用openid获取token的逻辑
     * TODO 两种情况：①用户存在，直接返回token；②用户不存在，save()保存用户信息后相当于注册了，再用uid生成token
     * @param session
     * @return
     */
    private String registerUser(Map<String,Object> session){
        // 获取 openid
        String openid = (String)session.get("openid");
        if(openid == null){
            throw new ParameterException(20004);
        }
        // 根据openid 查询用户
        Optional<User> userOptional = this.userRepository.findByOpenid(openid);
        // 用户存在则返回 JWT 令牌
        if(userOptional.isPresent()){
            // TODO:返回JWT令牌，
            // 当前不设置用户等级scope，使用默认值8
            return JwtToken.makeToken(userOptional.get().getId());
        }
        // 用户不存在，新增注册用户
        User user = User.builder()
                .openid(openid)
                .build();
        userRepository.save(user);
        // TODO: 返回JWT令牌
        Long uid = user.getId();
        return JwtToken.makeToken(uid);
    }
}
